﻿using System.Threading;
using NUnit.Framework;
using Present.Commands.Async.Actions;
using Present.Commands.Async.Actions.Decorators;
using Rhino.Mocks;

namespace Present.Commands.Tests
{
    [TestFixture]
    public class BusyCommandTargetTestCase : TestCase
    {
        private IBusyable busyable;
        private IAsyncAction<object, object> innerTarget;
        private BusyAsyncActionDecorator<object, object> action;

        public override void Setup()
        {
            base.Setup();

            busyable = MockRepository.GenerateStub<IBusyable>();
            innerTarget = MockRepository.GenerateStub<IAsyncAction<object, object>>();
            action = new BusyAsyncActionDecorator<object, object>(innerTarget,  busyable);
        }

        [Test]
        public void BusyIsResetOnErrors()
        {
            busyable.IsBusy = true;
            action.HandleError(null);
            Assert.IsFalse(busyable.IsBusy);
        }

        [Test]
        public void BusyIsResetOnSuccess()
        {
            busyable.IsBusy = true;
            action.HandleSuccess(null);
            Assert.IsFalse(busyable.IsBusy);
        }

        [Test]
        public void CanNotExecuteWhilstAlreadyExecuting()
        {

            var execution = new ManualResetEvent(false);
            var executionStarted = new ManualResetEvent(false);
            innerTarget
                .Stub(x => x.DoWork(null))
                .WhenCalled(i =>
                                {
                                    executionStarted.Set();
                                    execution.WaitOne(1000);
                                });

            RunOnBackgroundThread(() => action.DoWork(null));
            
            
            executionStarted.WaitOne(1000);
            Assert.IsFalse(action.CanExecute(null));
            execution.Set();

        }
    }

}
